package org.tri.gui.worker;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.tri.persistence.PersistenceManager;

/**
 * La clase {@code TransientWorker} es un worker que se encarga de eliminar 
 * entidades de la base datos en un thread diferente del de Swing.
 * @author kiira
 * @version 1.0, Feb 16, 2012
 */
public class TransientWorker extends SwingWorker {

    /** Objeto a eliminar. */
    protected Object objectToTransient;
    /** Lista de listeners del worker. */
    private List<TransientListener> listenerList;

    /**
     * Iniciliaza el worker con el objeto a eliminar.
     * @param toTransient objeto a eliminar.
     */
    public TransientWorker( Object toTransient ) {
        objectToTransient = toTransient;
        
        listenerList = new ArrayList<TransientListener>();

    }//end constructor
    
    /**
     * Añade un listener a la lista de listeners del worker.
     * @param listener 
     */
    public final void addTransientListener( TransientListener listener ) {
        listenerList.add( listener );

    }//end método addTransientListener

    /**
     * Quita un listener de la lista de listeners del worker.
     * @param listener listener a eliminar.
     */
    public final void removePersistenceListener( TransientListener listener ) {
        listenerList.remove( listener );

    }//end método removePersistenceListener

    /**
     * Este método es llamado cunado el worker terminó de realizar todas 
     * las tareas necesarias para eliminar el objeto; es llamado incluso
     * si el proceso falló.
     * Informa a todos los listeners que se completo el proceso.
     */
    protected final void fireDoneTrasit() {
        for ( final TransientListener listener : listenerList )
            SwingUtilities.invokeLater( new Runnable() {

                @Override
                public void run() {
                    listener.doneTransit();
                }

            } );

    }//end métdoo fireDoneTrasit

    /**
     * Este método es llamado exclusivamente cuando ocurre un error durante
     * la eliminación del objeto.
     * Informa a todos los listeners de la situación.
     * @param ex excepción generada por el error.
     */
    protected final void fireErrorTransit( final ExecutionException ex ) {
        for ( final TransientListener listener : listenerList )
            SwingUtilities.invokeLater( new Runnable() {

                @Override
                public void run() {
                    listener.errorTransit( ex );
                }

            } );

    }//end método fireErrorTransit
    
    /**
     * {@inheritDoc} 
     */
    @Override
    protected Object doInBackground() throws Exception {               
        //eliminamos el objeto
        PersistenceManager.makeTransient( objectToTransient );

        return null;

    }//end método doInBackground
    
    /**
     * Comprueba si ocurrieron errore durante la eliminación y envia los 
     * eventos correspondientes a los listeners.
     */
    @Override
    protected void done() {
        try {
            //comprobamos que termino con exito
            get();

        } catch ( InterruptedException ex ) {
        } catch ( ExecutionException ex ) {
            fireErrorTransit( ex );

        } finally {
            fireDoneTrasit();

        }

    }//end método done

}//end clase TransientWorker
